// 注解：使用该组件的方式：

//  <Prompt
// 				when={true}
// 				message={() => {
// 					confirmModal({
// 						msg: '内容已更改，尚未保存，确定要退出吗？',
// 					})
// 					return false
// 				}}
// 			/>
// 如上：when=true 代表该页面在离开前需要做一个路由切换的拦截
// message return false代表停留当前页面，true代表切换路由

import React, { useEffect } from 'react'
import { history } from './browserRouter'
import { Blocker, Location } from 'history'
import { useLocation, useNavigate } from 'react-router-dom'
import { Alert } from '../Modal'
type Props = {
	/**when=true 代表该页面在离开前需要做一个路由切换的拦截 */
	when: boolean
	/** return false代表停留当前页面，true代表切换路由*/
	message?: string | (() => boolean) | (() => Promise<boolean>)
}

const Prompt: React.FC<Props> = (props) => {
	const location = useLocation()
	const navigate = useNavigate()

	// 存储关闭阻止页面切换的方法（调用此方法将关闭阻止页面切换）
	let unblock: any = null

	// 阻止页面卸载
	const beforeUnload = (event: any) => {
		event.preventDefault()
		event.returnValue = ''
	}
	// 页面切换时的回调
	const handlePageChange: Blocker = async ({ location: nextLocation }) => {
		// 是否关闭切换限制并跳转
		let toNext: boolean = false
		if (props.message) {
			if (typeof props.message === 'string') {
				Alert(props.message)
			} else {
				toNext = await props.message()
			}
		} else {
			// toNext = confirm('是否放弃更改')
		}
		toNext && closeBlockAndNavigate(nextLocation)
	}

	// 关闭阻止页面切换
	const closeBlockPageSwitching = () => {
		if (unblock) {
			unblock()
			unblock = null
			window.removeEventListener('beforeunload', beforeUnload)
			// window.removeEventListener('hashchange', beforeUnHashchange)
		}
	}

	// 关闭阻止页面切换，并跳转
	const closeBlockAndNavigate = (nextLocation: Location) => {
		closeBlockPageSwitching()
		navigate(nextLocation)
	}

	// 监听when 和 pathname 、message 变化，当发生变化时判断是否需要开启block navigate.
	useEffect(() => {
		if (props.when) {
			// 阻塞页面跳转（history行为）
			unblock = history.block(handlePageChange)
			window.addEventListener('beforeunload', beforeUnload)
		}
		return () => {
			props.when && closeBlockPageSwitching()
		}
	}, [props.when, location.pathname, location.hash, props.message])

	return <></>
}

export default Prompt
